﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pavilion.GameTools;

namespace Pavilion.Locks
{
    class MirrorCharacterInputLockMonitor : LockMonitorBase
    {
        public override ILock Lock { get { return mirrorCharacterInputLock; } }

        private MirrorCharacterInputLock mirrorCharacterInputLock;
        private PhysicalTypeTool physicalTool;
        private CharacterInputTool characterInputTool;
        private CharacterInput currentInput;
        private bool isDisposed;

        public MirrorCharacterInputLockMonitor(MirrorCharacterInputLock mirrorCharacterInputLock)
        {
            this.mirrorCharacterInputLock = mirrorCharacterInputLock;
        }

        public override void Dispose()
        {
            characterInputTool.PressedInputChanged -= new Action<IEnumerable<CharacterInput>>(CharacterInputTool_PressedInputChanged);
            characterInputTool.ReleasedInputChanged -= new Action<IEnumerable<CharacterInput>>(CharacterInputTool_ReleasedInputChanged);
            physicalTool.PolygonData.IsFlippedHorizontallyChanged -= new Action<PhysicalData>(PolygonData_IsFlippedHorizontallyChanged);

            mirrorCharacterInputLock = null;
            characterInputTool = null;
            isDisposed = true;
        }

        public override void Load(GameItem gameItem)
        {
            characterInputTool = gameItem.ObtainTool<CharacterInputTool>();
            physicalTool = gameItem.ObtainTool<PhysicalTypeTool>();

            physicalTool.PolygonData.IsFlippedHorizontallyChanged += new Action<PhysicalData>(PolygonData_IsFlippedHorizontallyChanged);
            characterInputTool.PressedInputChanged += new Action<IEnumerable<CharacterInput>>(CharacterInputTool_PressedInputChanged);
            characterInputTool.ReleasedInputChanged += new Action<IEnumerable<CharacterInput>>(CharacterInputTool_ReleasedInputChanged);

            UpdateCurrentInput();
            UpdateLock();
        }

        public override void UpdateLock()
        {
            if (isDisposed)
                return;

            if (mirrorCharacterInputLock.IsPressed)
                IsOpen = characterInputTool.PressedInput.Contains(currentInput);
            else
                IsOpen = characterInputTool.ReleasedInput.Contains(currentInput);
        }

        private void UpdateCurrentInput()
        {
            if (physicalTool.PolygonData.IsFlippedHorizontally)
                currentInput = mirrorCharacterInputLock.MirrorInput;
            else
                currentInput = mirrorCharacterInputLock.RegularInput;
        }

        private void CharacterInputTool_PressedInputChanged(IEnumerable<CharacterInput> pressedInput)
        {
            UpdateLock();
        }

        private void CharacterInputTool_ReleasedInputChanged(IEnumerable<CharacterInput> releasedInput)
        {
            UpdateLock();
        }

        private void PolygonData_IsFlippedHorizontallyChanged(PhysicalData data)
        {
            UpdateCurrentInput();
            UpdateLock();
        }
    }
}
